<!DOCTYPE html>
<html>

<head>
  <title>A IO thread and a worker thread walk into a bar: a microbenchmark story</title>
  <script id="adobe_dtm" src="https://www.redhat.com/dtm.js" type="text/javascript"></script>
  <script src="/assets/javascript/highlight.pack.js" type="text/javascript"></script>
  <META HTTP-EQUIV='Content-Security-Policy' CONTENT="default-src 'none'; script-src 'self' 'unsafe-eval' 'sha256-ANpuoVzuSex6VhqpYgsG25OHWVA1I+F6aGU04LoI+5s=' 'sha256-ipy9P/3rZZW06mTLAR0EnXvxSNcnfSDPLDuh3kzbB1w=' js.bizographics.com https://www.redhat.com assets.adobedtm.com jsonip.com https://ajax.googleapis.com https://www.googletagmanager.com https://www.google-analytics.com https://use.fontawesome.com; style-src 'self' https://fonts.googleapis.com https://use.fontawesome.com; img-src 'self' *; media-src 'self' ; frame-src https://www.googletagmanager.com https://www.youtube.com; frame-ancestors 'none'; base-uri 'none'; object-src 'none'; form-action 'none'; font-src 'self' https://use.fontawesome.com https://fonts.gstatic.com;">
  <META HTTP-EQUIV='X-Frame-Options' CONTENT="DENY">
  <META HTTP-EQUIV='X-XSS-Protection' CONTENT="1; mode=block">
  <META HTTP-EQUIV='X-Content-Type-Options' CONTENT="nosniff">
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="description" content="Quarkus: Supersonic Subatomic Java">
  <meta name="twitter:card" content="summary_large_image">
  <meta name="twitter:site" content="@QuarkusIO"> 
  <meta name="twitter:creator" content="@QuarkusIO">
  <meta property="og:url" content="https://quarkus.io/blog/io-thread-benchmark/" />
  <meta property="og:title" content="A IO thread and a worker thread walk into a bar: a microbenchmark story" />
  <meta property="og:description" content="Quarkus: Supersonic Subatomic Java" />
  <meta property="og:image" content="/assets/images/quarkus_card.png" />
  <link rel="canonical" href="https://quarkus.io/blog/io-thread-benchmark/">
  <link rel="shortcut icon" type="image/png" href="/favicon.ico" >
  <link rel="stylesheet" href="https://quarkus.io/guides/stylesheet/config.css" />
  <link rel="stylesheet" href="/assets/css/main.css" />
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/all.css" integrity="sha384-lKuwvrZot6UHsBSfcMvOkWwlCMgc0TaWr+30HWe3a4ltaBwTZhyTEggF5tJv8tbt" crossorigin="anonymous">
  <link rel="alternate" type="application/rss+xml"  href="https://quarkus.io/feed.xml" title="Quarkus">
  <script src="https://quarkus.io/assets/javascript/goan.js" type="text/javascript"></script>
  <script src="https://quarkus.io/assets/javascript/hl.js" type="text/javascript"></script>
</head>

<body class="post">
  <!-- Google Tag Manager (noscript) -->
  <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-NJWS5L"
  height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
  <!-- End Google Tag Manager (noscript) -->

  <div class="nav-wrapper">
  <div class="grid-wrapper">
    <div class="width-12-12">
      <input type="checkbox" id="checkbox" />
      <nav id="main-nav" class="main-nav">
  <div class="container">
    <div class="logo-wrapper">
      
        <a href="/"><img src="/assets/images/quarkus_logo_horizontal_rgb_600px_reverse.png" class="project-logo" title="Quarkus"></a>
      
    </div>
    <label class="nav-toggle" for="checkbox">
      <i class="fa fa-bars"></i>
    </label>
    <div id="menu" class="menu">
      <span>
        <a href="/get-started/" class="">Get Started</a>
      </span>
      <span>
        <a href="/guides/" class="">Guides</a>
      </span>
      <span>
        <a href="/community/" class="">Community</a>
      </span>
      <span>
        <a href="/support/" class="">Support</a>
      </span>
      <span>
        <a href="/blog/" class="active">Blog</a>
      </span>
      <span>
        <a href="https://code.quarkus.io" class="button-cta secondary white">Start Coding</a>
      </span>
    </div>
  </div>
      </nav>
    </div>
  </div>
</div>

  <div class="content">
    <div class="post-page grid-wrapper">
  <div class="width-8-12 width-12-12-m doc-content">
    <div class="grid-wrapper">
      <div class="width-12-12">
        <p>
          <a href="/blog"><i class="fas fa-angle-left"></i> Back to all posts</a>
        </p>
      </div>
      <div class="width-12-12">
        <div class="post-date">
          April 21, 2020 
          
            <span class="tags"><a href="/blog/tag/performance">#performance</a></span>
          
        </div>
        <h1 class="post-title">A IO thread and a worker thread walk into a bar: a microbenchmark story</h1>
        <div class="grid-wrapper">
          <div class="width-8-12 width-12-12-m byline-wrapper">
            
            
              <img class="headshot" src="https://www.gravatar.com/avatar/55ac8578d32a08d68b078e47f29105b0">
            
            <p class="byline">By Emmanuel Bernard</p>
          </div>
          <div class="width-12-12">
              <div class="paragraph">
<p>A competitor recently published a microbenchmark comparing the performance of their stack to Quarkus.
The Quarkus team feels this microbenchmark shouldn’t be taken at face value because it wasn’t making a like-to-like comparison leading to incorrect conclusions.
Both of the two frameworks under comparison support reactive processing.
Reactive processing enables running the business logic directly on the <em>IO thread</em>, which ultimately performs better in microbenchmark focusing on response time and concurrency.
The microbenchmark should have been written so that both frameworks (or neither framework) obtain this benefit.
Anyway, this turns out to be a very interesting topic and good information for Quarkus users, so read on.</p>
</div>
<div class="sect1">
<h2 id="tl-dr"><a class="anchor" href="#tl-dr"></a>tl; dr;</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Quarkus <a href="https://quarkus.io/blog/runtime-performance/">has great performance</a> for both imperative and reactive workloads.
It’s because Quarkus is itself based on Eclipse Vert.x, a mature top performing reactive framework, in such a way that allows you to layer, mix and match the IO paradigm that best fits your use-case.</p>
</div>
<div class="paragraph">
<p>If you have a REST scenario well suited to run <em>purely on the IO thread</em>, add a Vert.x Reactive Route using <a href="https://quarkus.io/guides/reactive-routes">Quarkus Reactive Routes</a> and your app will get better performance than using Quarkus RESTEasy.</p>
</div>
<div class="paragraph">
<p>We ran this low-work REST + validation competitor-written microbenchmark which features no blocking operation, just returning static data.
When using Quarkus Reactive Routes to run Quarkus <em>purely on the IO thread</em>, <strong>we observed 2.6x times the requests/sec and 30% less memory usage (RSS)</strong> than running with Quarkus RESTEasy (which mixes IO thread and worker thread).
But that’s on a microbenchmark purpose built to this specific scenario (more on that later).</p>
</div>
<div class="imageblock">
<div class="content">
<img src="/assets/images/posts/iothread-benchmark/throughput.png" alt="throughput">
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="more-interesting-read"><a class="anchor" href="#more-interesting-read"></a>More interesting read</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The microbenchmark itself is uninteresting, but it is a good demonstrator of a phenomenon that can happen in reactive stacks.
Let’s use it as a vehicle to learn more about Quarkus and its reactive engine.</p>
</div>
<div class="sect2">
<h3 id="imperative-and-reactive-the-elevator-pitch"><a class="anchor" href="#imperative-and-reactive-the-elevator-pitch"></a>Imperative and Reactive: the elevator pitch</h3>
<div class="paragraph">
<p>This blog post does not explain the fundamental differences between the imperative execution model and the reactive execution model.
However, to understand why we see so much difference in the mentioned microbenchmark, we need some notions.</p>
</div>
<div class="paragraph">
<p>In general, Java web applications use imperative programming combined with blocking IO operations.
This is incredibly popular because it is easier to reason about the code.
<em>Things</em> get executed sequentially.
To make sure one request is not affected by another, they are run on different threads.
When your workload needs to interact with a database or another remote service, it relies on blocking IO.
The thread is blocked waiting for the answer.
Other requests running on different threads are not slowed down significantly.
But this means one thread for every concurrent request, which limits the overall concurrency.</p>
</div>
<div class="paragraph">
<p>On the other side, the reactive execution model embraces asynchronous development models and non blocking IOs.
With this model, multiple requests can be handled by the same thread.
When the processing of a request cannot make progress anymore (because it requests a remote service, or interacts with a database), it uses non blocking IO.
This releases the thread immediately, which can then be used to serve another request.
When the result of the IO operation is available, the processing of the request is restored and continues its execution.
This model enables the usage of the <em>IO thread</em> to handle multiple requests.
There are two significant benefits.
First, the response time is smaller because it does not have to jump to another thread.
Second, it reduces memory consumption as it decreases the usage of threads.
The reactive model uses the hardware resources more efficiently, but&#8230;&#8203; there is a significant drawback.
If the processing of a request starts to block, this gets real bad.
No other request can be handled.
To avoid this, you need to learn how to write non blocking code, how to structure asynchronous processing, and how to use non blocking IOs.
It&#8217;s a paradigm shift.</p>
</div>
<div class="paragraph">
<p>In Quarkus, we want to make the shift as easy as possible.
However, we have observed that the majority of user applications are written using the imperative model.
That is why, when the user application uses JAX-RS, Quarkus defaults to execute the (imperative) workload to a <em>worker thread</em>.</p>
</div>
</div>
<div class="sect2">
<h3 id="hello-world-microbenchmark-io-thread-or-worker-thread"><a class="anchor" href="#hello-world-microbenchmark-io-thread-or-worker-thread"></a>Hello world microbenchmark: IO thread or worker thread?</h3>
<div class="paragraph">
<p>Back to the competitor’s microbenchmark, we have a REST endpoint doing some trivial processing and some equally trivial validation.
Pretty much no meaningful business work.
This is the Hello World of REST for all intents and purposes.</p>
</div>
<div class="paragraph">
<p>When you run the microbenchmark with Quarkus RESTEasy, the request is handled by the reactive engine on the <em>IO thread</em> but then the processing work is handed over to a second thread from the <em>worker thread pool</em>.
That’s called <em>dispatch</em>.
When your microbenchmark does as little as Hello World, then the dispatch overhead is proportionally big.
The dispatch overhead is not visible in most (real life) applications but is very visible in artificial constructs like microbenchmarks.</p>
</div>
<div class="paragraph">
<p>The competitor’s stack, however, runs all the request operations on the IO thread by default.
So what this microbenchmark was actually comparing is just the cost of dispatching to the worker thread pool.
And frankly (according to the competitor&#8217;s numbers) and in spite of this extra dispatch work, Quarkus did very very well achieving ~95% of the competitor’s throughput today!  I say today because we are always improving upon performance, and in fact we expect to see further gains in the soon to be released 1.4 release.</p>
</div>
<div class="paragraph">
<p><strong>When compared at a disadvantage (dispatching to a worker thread), Quarkus is nevertheless almost as fast in throughput.</strong></p>
</div>
<div class="paragraph">
<p>… But wait, Quarkus can also avoid the dispatch altogether and run operations on the IO Thread.
This is a more accurate comparison to how the competitor' stack was configured to do as in both case, it is the user&#8217;s responsibility to ask for a dispatch if and when needed by the application.
To compare apples to apples, let’s use <a href="https://quarkus.io/guides/reactive-routes">Quarkus Reactive Routes</a> backed by Eclipse Vert.x.
In this model, operations are run on the IO thread by default.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@ApplicationScoped
public class MyDeclarativeRoutes {

  @Inject
  Validator validator;

  @Route(path = "/hello/:name", methods = HttpMethod.GET)
  void greetings(RoutingExchange ex) {
    RequestWrapper requestWrapper = new RequestWrapper(ex.getParam("name").orElse("world"));
    Set&lt;ConstraintViolation&lt;RequestWrapper&gt;&gt; violations = validator.validate(requestWrapper));
    if( violations.size() == 0) {
      ex.ok("hello " + requestWrapper.name);
    } else {
      StringBuilder validationError = new StringBuilder();
      violations.stream().forEach(violation -&gt; validationError.append(violation.getMessage()));
      ex.response().setStatusCode(400).end(validationError.toString());
    }
  }

  private class RequestWrapper {
    @NotBlank
    public String name;

    public RequestWrapper(String name) {
      this.name = name;
    }
  }

}</code></pre>
</div>
</div>
<div class="paragraph">
<p>This is not very different from your JAX-RS equivalent.</p>
</div>
</div>
<div class="sect2">
<h3 id="throughput-numbers"><a class="anchor" href="#throughput-numbers"></a>Throughput Numbers</h3>
<div class="paragraph">
<p>We ran the microbenchmark application in a docker container constrained to reflect a typical resource allocation to a container orchestrated by Kubernetes:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>4 CPU</p>
</li>
<li>
<p>256 MB of RAM</p>
</li>
<li>
<p>and <code>-Xmx128m</code> heap usage for the Java process</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>We saw that Quarkus using Reactive Routes ran 2.6 times the requests/sec.
2.6 times!
It makes sense! Remember the application code virtually does nothing, so the dispatch cost is comparatively high.
If you were to write a more real life workload (maybe even having a blocking operation like a JPA access and therefore forcing a dispatch), then the results would be very different.
Context matters!</p>
</div>
<div class="paragraph">
<p>You can find code and how to reproduce the microbenchmark <a href="https://github.com/johnaohara/quarkus-iothread-workerpool/tree/1.3.1.Final">here on GitHub</a>.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<caption class="title">Table 1. Microbenchmark results comparing Quarkus dispatching to a worker thread vs running purely on the IO thread</caption>
<colgroup>
<col style="width: 25%;">
<col style="width: 25%;">
<col style="width: 25%;">
<col style="width: 25%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Quarkus - 1.3.1.Final - 4 CPU&#8217;s</th>
<th class="tableblock halign-right valign-top">Worker thread</th>
<th class="tableblock halign-right valign-top">IO thread</th>
<th class="tableblock halign-right valign-top">Ratio</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Mean Start Time to First Request (ms) <sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup></p></td>
<td class="tableblock halign-right valign-top"><p class="tableblock">993.9</p></td>
<td class="tableblock halign-right valign-top"><p class="tableblock">868.3</p></td>
<td class="tableblock halign-right valign-top"><p class="tableblock">87.4%</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Max RSS (MB)</p></td>
<td class="tableblock halign-right valign-top"><p class="tableblock">138.8</p></td>
<td class="tableblock halign-right valign-top"><p class="tableblock">97.9</p></td>
<td class="tableblock halign-right valign-top"><p class="tableblock">70.5%</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Max Throughput (req/sec)</p></td>
<td class="tableblock halign-right valign-top"><p class="tableblock">46,172.2</p></td>
<td class="tableblock halign-right valign-top"><p class="tableblock">123,520.4</p></td>
<td class="tableblock halign-right valign-top"><p class="tableblock">267.5%</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Max Req/Sec/MB</p></td>
<td class="tableblock halign-right valign-top"><p class="tableblock">332.7</p></td>
<td class="tableblock halign-right valign-top"><p class="tableblock">1,262.1</p></td>
<td class="tableblock halign-right valign-top"><p class="tableblock">379.4%</p></td>
</tr>
</tbody>
</table>
<div class="imageblock">
<div class="content">
<img src="/assets/images/posts/iothread-benchmark/throughput-percentile.png" alt="throughput percentile">
</div>
</div>
<div class="paragraph">
<p><strong>In a fair comparison (purely remaining on the IO thread - no dispatch), Quarkus more than double its throughput.</strong></p>
</div>
<div class="paragraph">
<p>As the generated load tends towards the maximum throughput of the system under test, the response time experienced by the client increases exponentially.
So the best system (for the workload) has a vertical line as far to the right as possible.
Equally important is to have as flat a line as possible for the longest time.
You do not want the response time to degrade before the system reaches maximum throughput.</p>
</div>
<div class="paragraph">
<p>By the way, in the competitor microbenchmark Quarkus is shown as consuming more RSS (more RAM).This is also explained by the worker thread pool being operated whereas the competitor did not have a worker thread pool.
The Quarkus Reactive Routes solution (on a pure IO event run) shows a 30% RSS usage reduction.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="/assets/images/posts/iothread-benchmark/rss.png" alt="rss">
</div>
</div>
<div class="paragraph">
<p>In this graph, the lower, the better.
We see that the pure IO thread solution manages to increase throughput with little to no change to the memory usage (RSS), that&#8217;s very good!</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="conclusion"><a class="anchor" href="#conclusion"></a>Conclusion</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Quarkus offers you the ability to safely run blocking operations, run non blocking operations on the IO thread or mix both models.
The Quarkus team takes performance very seriously and we see Quarkus as offering great numbers whether you use the imperative or reactive models.
In more realistic workloads, the dispatch cost would be much less significant, you would not see such drastic differences between the two approaches.
As usual, test as close to your real application as possible.</p>
</div>
<div class="paragraph">
<p>Mystery solved.
Benchmarks are hard, challenge them.
But the moral of the story is that in all bad comes some good.
We’ve now learned how to run Quarkus applications entirely on the IO thread.
And how in some situations that can make a big difference.
Remember, don’t block! In fact, Quarkus <a href="https://quarkus.io/guides/all-config#quarkus-vertx-core_quarkus.vertx.warning-exception-time">can warn you if you do so</a>.
Oh and we also learned that Quarkus is so fast, it can even beat itself ;p</p>
</div>
</div>
</div>
<div id="footnotes">
<hr>
<div class="footnote" id="_footnotedef_1">
<a href="#_footnoteref_1">1</a>. ‘Mean Start Time to First Request’ was measured using an application built as an UberJar
</div>
</div>
              
          </div>
          <div class="width-12-12"><div class="share-page">
  <a class="share-linkedin" href="https://www.linkedin.com/shareArticle?mini=true&url=https://quarkus.io/blog/io-thread-benchmark/&title=A IO thread and a worker thread walk into a bar: a microbenchmark story" rel="nofollow" target="_blank" title="Share on LinkedIn">
    <img src="/assets/images/share-page/icons_social-linkedin.png"/>
  </a>
  <a class="share-twitter" href="https://twitter.com/intent/tweet?text=A IO thread and a worker thread walk into a bar: a microbenchmark story&url=https://quarkus.io/blog/io-thread-benchmark/&via=quarkusio&related=quarkusio" rel="nofollow" target="_blank" title="Share on Twitter">
    <img src="/assets/images/share-page/icons_social-twitter.png"/>
  </a>
  <a class="share-facebook" href="https://facebook.com/sharer.php?u=https://quarkus.io/blog/io-thread-benchmark/" rel="nofollow" target="_blank" title="Share on Facebook">
    <img src="/assets/images/share-page/icons_social-facebook.png"/>
  </a>
  <a class="share-reddit" href="http://www.reddit.com/submit?url=https://quarkus.io/blog/io-thread-benchmark/" onclick="window.open(this.href, 'pop-up', 'left=20,top=20,width=900,height=500,toolbar=1,resizable=0'); return false;" title="Share on Reddit" >
    <img src="/assets/images/share-page/icons_social-reddit.png"/>
  </a>
  <a class="share-email" href="mailto:?subject=A IO thread and a worker thread walk into a bar: a microbenchmark story&amp;body=A IO thread and a worker thread walk into a bar: a microbenchmark story https://quarkus.io/blog/io-thread-benchmark/" title="Share via Email" >
    <img src="/assets/images/share-page/icons_social-email.png"/>
  </a>
</div>
</div>
        </div>
      </div>
    </div>
  </div>
</div>

  </div>

  <div class="content project-footer">
  <div class="footer-section">
    <div class="logo-wrapper">
      <a href="/"><img src="/assets/images/quarkus_logo_horizontal_rgb_reverse.svg" class="project-logo" title="Quarkus"></a>
    </div>
  </div>
  <div class="grid-wrapper">
    <p class="grid__item width-3-12">Quarkus is open. All dependencies of this project are available under the <a href='https://www.apache.org/licenses/LICENSE-2.0' target='_blank'>Apache Software License 2.0</a> or compatible license.<br /><br />This website was built with <a href='https://jekyllrb.com/' target='_blank'>Jekyll</a>, is hosted on <a href='https://pages.github.com/' target='_blank'>Github Pages</a> and is completely open source. If you want to make it better, <a href='https://github.com/quarkusio/quarkusio.github.io' target='_blank'>fork the website</a> and show us what you’ve got.</p>

    
      <div class="width-1-12 project-links">
        <span>Navigation</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="/">Home</a></li>
          
            <li><a href="/guides">Guides</a></li>
          
            <li><a href="/community/#contributing">Contribute</a></li>
          
            <li><a href="/faq">FAQ</a></li>
          
            <li><a href="/get-started">Get Started</a></li>
          
        </ul>
      </div>
    
      <div class="width-1-12 project-links">
        <span>Contribute</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="https://twitter.com/quarkusio">Follow us</a></li>
          
            <li><a href="https://github.com/quarkusio">GitHub</a></li>
          
            <li><a href="/security">Security&nbsp;policy</a></li>
          
        </ul>
      </div>
    
      <div class="width-1-12 project-links">
        <span>Get Help</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="https://groups.google.com/forum/#!forum/quarkus-dev">Forums</a></li>
          
            <li><a href="https://quarkusio.zulipchat.com">Chatroom</a></li>
          
        </ul>
      </div>
    

    
      <div class="width-3-12 more-links">
        <span>Quarkus is made of community projects</span>
        <ul class="footer-links">
          
            <li><a href="https://vertx.io/" target="_blank">Eclipse Vert.x</a></li>
          
            <li><a href="https://microprofile.io" target="_blank">Eclipse MicroProfile</a></li>
          
            <li><a href="https://hibernate.org" target="_blank">Hibernate</a></li>
          
            <li><a href="https://netty.io" target="_blank">Netty</a></li>
          
            <li><a href="https://resteasy.github.io" target="_blank">RESTEasy</a></li>
          
            <li><a href="https://camel.apache.org" target="_blank">Apache Camel</a></li>
          
            <li><a href="https://code.quarkus.io/" target="_blank">And many more...</a></li>
          
        </ul>
      </div>
    
  </div>
</div>
  <div class="content redhat-footer">
  <div class="grid-wrapper">
    <span class="licence">
      <i class="fab fa-creative-commons"></i><i class="fab fa-creative-commons-by"></i> <a href="https://creativecommons.org/licenses/by/3.0/" target="_blank">CC by 3.0</a> | <a href="https://www.redhat.com/en/about/privacy-policy">Privacy Policy</a>
    </span>
    <span class="redhat">
      Sponsored by
    </span>
    <span class="redhat-logo">
      <a href="https://www.redhat.com/" target="_blank"><img src="/assets/images/redhat_reversed.svg"></a>
    </span>
  </div>
</div>


  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js" integrity="sha384-8gBf6Y4YYq7Jx97PIqmTwLPin4hxIzQw5aDmUg/DDhul9fFpbbLcLh3nTIIDJKhx" crossorigin="anonymous"></script>
  <script type="text/javascript" src="/assets/javascript/mobile-nav.js"></script>
  <script type="text/javascript" src="/assets/javascript/scroll-down.js"></script>
  <script src="/assets/javascript/satellite.js" type="text/javascript"></script>
  <script src="https://quarkus.io/guides/javascript/config.js" type="text/javascript"></script>
  <script src="/assets/javascript/search-filter.js" type="text/javascript"></script>
  <script src="/assets/javascript/back-to-top.js" type="text/javascript"></script>
</body>

</html>
